在iOS开发过程中,正则的使用还是比较常见,用来判断用户名、手机号等的输入。当碰到这种需求的时候,部分开发的第一印象可能是使用 NSPredicateSELF MATCHES %@ 进行判断,但遗憾的是此方法并非万能,存在检查不出来的情况。其实苹果专门提供了 NSRegularExpression 这个类来做正则校验。

NSPredicate

NSPredicate 可能是我们一开始接触iOS正则实现的方法,但现实是它只能简单的完成正则功能,并没有 NSRegularExpression 强大,同时还存在校验不出来的情况。

NSString *regEx = @"<正则表达式>";
NSString *string = @"<待匹配的字符串>";

NSPredicate *predicate = [NSPredicate predicateWithFormat:@"SELF MATCHES %@", regEx];
BOOL matched = [predicate evaluateWithObject:string];
NSLog(@"是否匹配 = %d", matched);

NSRegularExpression,真正的正则实现

初始化NSRegularExpression

/// 初始化NSRegularExpression,如果出错则会返回nil,并带有error
/// @param pattern 正则表达式
/// @param options 模式选项,一般设成 kNilOptions
/// @parma error 错误
+ (nullable NSRegularExpression *)regularExpressionWithPattern:(NSString *)pattern options:(NSRegularExpressionOptions)options error:(NSError **)error;

关于NSRegularExpressionOptions

typedef NS_OPTIONS(NSUInteger, NSRegularExpressionOptions) {
   NSRegularExpressionCaseInsensitive             = 1 << 0, //不区分字母大小写的模式
   NSRegularExpressionAllowCommentsAndWhitespace  = 1 << 1, //忽略掉正则表达式中的空格和#号之后的字符
   NSRegularExpressionIgnoreMetacharacters        = 1 << 2, //将正则表达式整体作为字符串处理
   NSRegularExpressionDotMatchesLineSeparators    = 1 << 3, //允许.匹配任何字符,包括换行符  
   NSRegularExpressionAnchorsMatchLines           = 1 << 4, //允许^和$符号匹配行的开头和结尾
   NSRegularExpressionUseUnixLineSeparators       = 1 << 5, //设置\n为唯一的行分隔符,否则所有的都有效。
   NSRegularExpressionUseUnicodeWordBoundaries    = 1 << 6 //使用Unicode TR#29标准作为词的边界,否则所有传统正则表达式的词边界都有效
};

前面提到 options 一般设成 kNilOptions,它的效果就是区分大小写,严格校验。

匹配

获取匹配的个数

NSString *regEx = @"<正则表达式>";
NSString *string = @"<待匹配的字符串>";
NSError *error;
NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:regEx options:kNilOptions error:&error];
if (error) {
    NSLog(@"error = %@", error);
}

NSUInteger number = [regularExpression numberOfMatchesInString:string options:kNilOptions range:NSMakeRange(0, string.length)];
NSLog(@"匹配的个数 = %lu", (unsigned long)number);

BOOL matched = (number != 0);
NSLog(@"是否匹配 = %d", matched);

获取第一个匹配的结果

NSString *regEx = @"<正则表达式>";
NSString *string = @"<待匹配的字符串>";
NSError *error;
NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:regEx options:kNilOptions error:&error];
if (error) {
    NSLog(@"error = %@", error);
}

NSTextCheckingResult *firstMatch = [regularExpression firstMatchInString:string options:0 range:NSMakeRange(0, string.length)];
if (firstMatch) {
    // NSTextCheckingResult 的 range 属性即匹配的字符串的位置
    NSString *matchedString = [string substringWithRange:firstMatch.range];
    NSLog(@"匹配的字符串 = %@", matchedString);       
}

获取所有匹配的结果

NSString *regEx = @"<正则表达式>";
NSString *string = @"<待匹配的字符串>";
NSError *error;
NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:regEx options:kNilOptions error:&error];
if (error) {
    NSLog(@"error = %@", error);
}

NSArray *matchArray = [regularExpression matchesInString:string options:0 range:NSMakeRange(0, string.length)];
for (NSTextCheckingResult *match in matchArray) {
    NSString *matchedString = [string substringWithRange:match.range];
    NSLog(@"匹配的字符串 = %@", matchedString); 
}

替换匹配的字符串

NSString *regEx = @"<正则表达式>";
NSString *string = @"<待匹配的字符串>";
NSString *replacingString = @"<替换的字符串>";
NSError *error;
NSRegularExpression *regularExpression = [NSRegularExpression regularExpressionWithPattern:regEx options:kNilOptions error:&error];
if (error) {
    NSLog(@"error = %@", error);
}

NSString *newString = [regularExpression stringByReplacingMatchesInString:string options:kNilOptions range:NSMakeRange(0, string.length) withTemplate:replacingString];
NSLog(@"替换后的字符串 = %@", newString); 

Kang
3 声望0 粉丝

Bug研发工程师正是在下,阁下是?